#include "resourcemanager.h"
#include "resource.h"
#include <d3d9.h>
#include "resourcedevicerendertarget.h"

namespace gunsmith
{
CResourceManager	*CResourceManager::m_pInstance	= NULL;
unsigned int		CResourceManager::m_iRefCount	= 0;

CResourceManager::CResourceManager()
{
	m_pDevice = NULL;
}

CResourceManager::~CResourceManager()
{
}

/*!	\brief		Returns a pointer to the manager instance and increments refcount.
	\return		CResourceManager*	Resource manager pointer.
	\remarks	
	\sa			*/
CResourceManager* CResourceManager::GetInstance()
{
	if(!m_pInstance)
		m_pInstance = new CResourceManager();

	++m_iRefCount;

	return m_pInstance;
}

/*!	\brief		Releases the manager and decrements refcount. (see remarks)
	\return		void
	\remarks	Will produce error if refcount <= 0.
	\sa			*/
void CResourceManager::Release()
{
	if(m_iRefCount <= 1)	// intended to make the program crash on sloppy usage
	{
		delete m_pInstance;
	}

	--m_iRefCount;
}

/*!	\brief		Returns the reference count of the resource manager.
	\return		unsigned int	Reference count.
	\remarks	
	\sa			*/
unsigned int CResourceManager::GetRefCount()
{
	return m_iRefCount;
}

/*!	\brief		Method to register a Direct3D device and add its surface as a CResourceDeviceRenderTarget.
	\param		pDevice	Direct3D device.
	\return		void
	\remarks	
	\sa			*/
void CResourceManager::RegisterDevice(IDirect3DDevice9 *pDevice)
{
	m_pDevice = pDevice;

	IDirect3DSurface9 *pSurface;
	HRESULT hr = m_pDevice->GetRenderTarget(0, &pSurface);
	CreateResource<CResourceDeviceRenderTarget>(RID_RENDERTARGET_DEVICE, pSurface);
	pSurface->Release();	// looks strange at this position, but otherwise I have memory leaks
}

/*!	\brief		Returns the Direct3D device.
	\return		IDirect3DDevice9*	Direct3D device.
	\remarks	
	\sa			*/
IDirect3DDevice9* CResourceManager::GetDevice() const
{
	return m_pDevice;
}

/*!	\brief		Cleans up the resources in the resource manager.
	\return		void
	\remarks	
	\sa			*/
void CResourceManager::FreeResources()
{
	m_mResType.clear();
	
	RESOURCEMAPBYNAME::iterator iterMap = m_mResName.begin();
	while(iterMap != m_mResName.end())
	{
		(*iterMap).second->Destroy();
		delete (*iterMap).second;
		iterMap = m_mResName.erase(iterMap);
	}
}

/*!	\brief		Returns an array of resources which match the resource name. (see remarks)
	\param		sResName	Resource name.
	\param		pNumRes	Size of resource array.
	\param		pppResource	Outputs an array of resource pointers.
	\return		bool
	\remarks	Use delete[] on the array if you don't need it anymore to avoid memory leaks.
	\sa			*/
bool CResourceManager::GetResourcesByName(std::string sResName, unsigned int *pNumRes, CResource ***pppResource)
{
	RESOURCEMAPBYNAME::iterator itFound = m_mResName.find(sResName);

	UINT NumRes = m_mResName.count(sResName);

	if(pNumRes != NULL)
		*pNumRes = NumRes;	

	if(NumRes <= 0 || pppResource == NULL)
		return (NumRes > 0);


	// get resources, create array and assign to pointer
	*pppResource = new CResource*[NumRes];

	unsigned int Count = 0;
	for(RESOURCEMAPBYNAME::iterator itRes = m_mResName.begin(); ; itRes++)
	{
		if((*itRes).first == sResName)
		{
			(*pppResource)[Count] = (*itRes).second;
			++Count;

			if(Count >= NumRes)
				return true;
		}
	}
}
};